package com.chenjun.designpattern.structural.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;

/**
 * 事先不要指定是前置增强还是后置增强,在代码中动态织入切面
 * @author Administrator
 *
 */
public class 手动实现AOP之动态织入切面
{
	public static void main(String[] args)
	{
		CalculatorHandle calculatorHandle = new CalculatorHandle(new CalculatorImpl());
		Calculator proxy = (Calculator) Proxy.newProxyInstance(Calculator.class.getClassLoader(), new Class[] { Calculator.class },calculatorHandle);
		System.out.println(proxy.calculate(10, 5));
	}
}

/**
 * 计算器类型_定义成抽象的
 * 
 * @author Administrator
 *
 */
interface Calculator
{
	/**
	 * 计算方法，具体运算步骤在子类中实现
	 * 
	 * @param a
	 * @param b
	 * @return
	 */
	public int calculate(int a, int b);
}

/**
 * 计算器类型具体实现类CalculatorImpl
 * 
 * @author Administrator
 *
 */
class CalculatorImpl implements Calculator
{
	@Override
	public int calculate(int a, int b)
	{
		return a / b;
	}
}

class CalculatorHandle implements InvocationHandler
{
	// 被代理的目标对象target
	private Object target;

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
	{
		return method.invoke(target, args);
	}

	public CalculatorHandle(Object obj)
	{
		this.target = obj;
	}
}

abstract class AbstractHandler implements InvocationHandler
{
	private Object targetObject;

	/**
	 * getter and setter
	 * 
	 * @return
	 */
	public Object getTargetObject()
	{
		return targetObject;
	}

	public void setTargetObject(Object targetObject)
	{
		this.targetObject = targetObject;
	}
}

abstract class BeforeHandler extends AbstractHandler
{
	public abstract void handleBefore(Object proxy, Method method, Object[] args);

	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
	{
		handleBefore(proxy, method, args);
		return method.invoke(getTargetObject(), args);
	}
}

abstract class afterHandler extends AbstractHandler
{
	public abstract void handleAfter(Object proxy, Method method, Object[] args);

	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
	{
		handleAfter(proxy, method, args);
		return method.invoke(getTargetObject(), args);
	}
}

/**
 * 创建Proxy的工厂类
 * @author Administrator
 *
 */
class ProxyFactory
{
	public static Object getProxy(Object targetObject,List<AbstractHandler> handlers)
	{
		for(AbstractHandler handler : handlers){
			handler.getTargetObject();
		}
		//Calculator calculatorProxy = (Calculator)Proxy.newProxyInstance(Calculator.class.getClassLoader(), new Class[] { Calculator.class } , abstractHandler);
		
		return calculatorProxy;
	}
}
